using Logic.Global;
using UnityEngine;
using UnityEngine.Rendering;

public enum DrawMode
{
    Draw = 0,
    Erase,
}

/// <summary>
/// 图片擦除、绘制组件
/// </summary>
public class DrawableExt : MonoBehaviour
{
    public Vector2 brushSize = new Vector2(3, 3);
    public Vector2 brushOffset = Vector2.zero;
    public float finishPercent = 0.6f;
    public bool canPaint = false;
    public Texture2D brushTex;
    public DrawMode drawMode = DrawMode.Erase;
    public float alphaValue = 0.3f;

    private RenderTexture targetRenderTexture;
    private Material mMat;
    private Material mPenMat;

    private Transform dressRoot;

    /// 起初所有的颜色
    private Color[] orig_Colors;

    /// 当前，绘制过程中。所有的颜色
    private Color[] cur_colors;

    /// 绘制目标的矩阵信息
    private Rect textureRect;

    /// 当前绘制的Texture
    private Texture2D drawTexture;

    /// 当前的操作目标精灵渲染器
    public SpriteRenderer TargetRenderer { get; private set; }

    /// 当前精灵图所在的矩阵信息
    public Rect TexRect
    {
        get
        {
            //需要根据不同的图形API做区分，规则不一样
            if (SystemInfo.graphicsDeviceType == GraphicsDeviceType.OpenGLES3 ||
                SystemInfo.graphicsDeviceType == GraphicsDeviceType.Metal)
            {
                return new Rect(textureRect.x / RTScaleFatio, textureRect.y / RTScaleFatio,
                    textureRect.width / RTScaleFatio, textureRect.height / RTScaleFatio);
            }

            return new Rect(textureRect.x / RTScaleFatio,
                (targetRenderTexture.height * RTScaleFatio - textureRect.y - textureRect.height) / RTScaleFatio,
                textureRect.width / RTScaleFatio, textureRect.height / RTScaleFatio);
        }
    }

    /// targetRenderTexture的缩放倍数
    private int RTScaleFatio = 4;

    /// 绘制时的尺寸缩放
    private float _drawScale = 1;

    public void InitPaint(SpriteRenderer targetRenderer)
    {
        if (TargetRenderer != null)
            TargetRenderer.material = new Material(Resources.Load<Material>("SpriteDefault"));

        TargetRenderer = targetRenderer;
        _drawScale = TargetRenderer.sprite.rect.width / (TargetRenderer.size.x * 100);
        Sprite sp = TargetRenderer.sprite;
        mMat = new Material(Resources.Load<Material>("SpriteMask"));
        mMat.SetInt("_MaskReverse", (int) drawMode);
        TargetRenderer.material = mMat;
        if (targetRenderTexture != null)
        {
            targetRenderTexture.Release();
        }

        textureRect = sp.textureRect;
        NewRenderTexture(sp.texture.width, sp.texture.height);
        TargetRenderer.sprite = sp;
        TargetRenderer.material.SetTexture("_MainTex", sp.texture);
        TargetRenderer.material.SetTexture("_MaskTex", targetRenderTexture);
        TargetRenderer.gameObject.SetActive(true);
        mPenMat = new Material(Resources.Load<Material>("SpritePen"));
        GetOrigColor();
        dressRoot = TargetRenderer.gameObject.transform;
        canPaint = true;
    }


    void GetOrigColor()
    {
        RenderTexture.active = targetRenderTexture;
        Texture2D tex = new Texture2D((int) TexRect.width, (int) TexRect.height, TextureFormat.RGB24, false);
        tex.name = $"Texture2D Make By {TargetRenderer.name} GetOrigColor()";
        tex.ReadPixels(TexRect, 0, 0);
        orig_Colors = tex.GetPixels();
        tex.Reinitialize(10, 10);
    }

    private void NewRenderTexture(int w, int h)
    {
        if (targetRenderTexture == null)
        {
            targetRenderTexture =
                RenderTexture.GetTemporary(w / RTScaleFatio, h / RTScaleFatio, 0, RenderTextureFormat.ARGB32);
            targetRenderTexture.name = $"RenderTex Make By {TargetRenderer.name} NewRenderTexture";
        }

        RenderTexture.active = targetRenderTexture;
        GL.Clear(true, true, Color.clear);
        RenderTexture.active = null;
    }

    private void OnDestroy()
    {
        drawTexture = null;
        RenderTexture.ReleaseTemporary(targetRenderTexture);
        // Util.ClearMemory();
    }

    /// 自动根据鼠标位置更新绘制
    public void UpdatePaintByMousePos(Vector2 offset = default)
    {
        if (!canPaint) return;
        Vector2 mouseWorldPos = GameCamera.Ins.gameCamera.ScreenToWorldPoint(Input.mousePosition);
        UpdatePaint(mouseWorldPos, offset);
    }

    /// 根据传入的世界坐标更新绘制
    public void UpdatePaint(Vector2 pos, Vector2 offset = default)
    {
        if (!canPaint) return;
        Vector2 worldPos = pos;
        worldPos += offset;
        worldPos += brushOffset;
        Vector2 localPos = dressRoot.transform.InverseTransformPoint(worldPos);
        localPos *= _drawScale;
        CopyTexture(localPos);
    }

    private void CopyTexture(Vector2 penPos)
    {
        //清空 GL
        GL.PushMatrix(); //GL入栈
        GL.LoadPixelMatrix(0, targetRenderTexture.width, targetRenderTexture.height, 0);
        RenderTexture.active = targetRenderTexture;
        Vector2 size = new Vector2(brushTex.width * brushSize.x, brushTex.height * brushSize.y);
        size = size / RTScaleFatio * _drawScale;
        float x = textureRect.x + textureRect.width / 2f + penPos.x * 100 - size.x / 2f;
        float y = targetRenderTexture.height * RTScaleFatio -
                  (textureRect.y + textureRect.height / 2f + penPos.y * 100 - size.y / 2f);
        Vector2 pos = new Vector2(x / RTScaleFatio, y / RTScaleFatio);
        // 居中绘制
        pos -= size / 2;
        Rect drawRect = new Rect(pos, size);
        mPenMat.SetFloat("_Alpha", alphaValue);
        Graphics.DrawTexture(drawRect, brushTex, mPenMat);
        RenderTexture.active = null;
        GL.PopMatrix();
    }

    // 判断是否胜利,耗费性能，勿频繁调用,1S内最多2次
    public bool JudgeWin(bool isManualGC = true)
    {
        float percent = GetDrawPercent();
        Debug.Log("percent: " + percent);
        if (percent > finishPercent)
        {
            Debug.Log("little game win");
            if (isManualGC)
            {
                canPaint = false;
                ClearRenderTexture();
            }

            return true;
        }

        return false;
    }

    /// 立即完成
    public void FinishAtOnce()
    {
        Debug.Log("little game win");
        canPaint = false;
        ClearRenderTexture();
    }

    public void ClearRenderTexture()
    {
        if (TargetRenderer == null) return;
        RenderTexture.active = targetRenderTexture;
        if (drawMode == DrawMode.Draw)
            GL.Clear(true, true, new Color(.5f, .5f, .5f, 1f));
        else
            GL.Clear(true, true, new Color(.5f, .5f, .5f, 0f));
        RenderTexture.active = null;
        TargetRenderer.material.SetTexture("_MaskTex", null);
        TargetRenderer.material = Resources.Load<Material>("SpriteDefault");
        Util.ClearMemory();
    }

    /// 当前绘制的比例,耗费性能，勿频繁调用,1S内最多2次
    public float GetDrawPercent()
    {
        var currentActiveRt = RenderTexture.active;
        RenderTexture.active = targetRenderTexture;
        if (drawTexture == null)
        {
            drawTexture = new Texture2D((int) TexRect.width, (int) TexRect.height);
            drawTexture.name = $"Texture2D Make By {TargetRenderer.name} GetPaintPercent()";
        }
        else
        {
            drawTexture.Reinitialize((int) TexRect.width, (int) TexRect.height);
        }

        drawTexture.ReadPixels(TexRect, 0, 0);
        RenderTexture.active = currentActiveRt;
        cur_colors = drawTexture.GetPixels();
        drawTexture.Reinitialize(10, 10);
        int forPaintCount = 0;
        int paintCount = 0;
        float alpha1 = 90 / 255f;
        float alpha2 = 10 / 255f;
        for (int i = 0; i < cur_colors.Length; i += 50)
        {
            if (orig_Colors[i].a >= alpha1)
            {
                forPaintCount++;
                if (cur_colors[i].a > alpha2)
                    paintCount++;
            }
        }

        float result = paintCount / (float) forPaintCount;
        result = Mathf.Clamp01(result);
        return result;
    }
}